package com.speedchina.permission.service.sys.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.speedchina.framework.base.TService;
import com.speedchina.framework.helper.Assert;
import com.speedchina.permission.base.sysenum.RoleEnum;
import com.speedchina.framework.utils.SnowFlake;
import com.speedchina.permission.base.constant.SysConstant;
import com.speedchina.permission.dao.sys.RoleDao;
import com.speedchina.permission.dao.sys.RoleResourceDao;
import com.speedchina.permission.domain.sys.entity.Role;
import com.speedchina.permission.domain.sys.entity.RoleResource;
import com.speedchina.permission.domain.sys.entity.User;
import com.speedchina.permission.domain.sys.po.RolePo;
import com.speedchina.permission.service.sys.RoleService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 系统-角色表 服务层实现类
 * @author han.qing
 * @date 2021-04-08 12:17:35
 */
@Service
public class RoleServiceImpl extends TService<RoleDao, Role> implements RoleService {

    @Resource
    RoleResourceDao roleResourceDao;

    /**
     * role是否唯一，不唯一false
     * 1.先保存角色基本信息
     * 2.再保存角色的资源信息
     * @param rolePo
     * @return
     */
    @Override
    public boolean save(RolePo rolePo) {
        Role role= baseMapper.selectOne(new LambdaQueryWrapper<Role>().eq(Role::getRoleKey,rolePo.getRoleKey()));
        Assert.isTrue(role!=null,RoleEnum.ROLE_KEY_EXIST.getMsg());
//        rolePo.setId(SnowFlake.generateId().toString());
//        baseMapper.insert(rolePo);
        super.saveOrUpdate4AutoGenId(rolePo);
        String resourceIds = rolePo.getResourceIds();
        saveRoleResource(resourceIds,rolePo.getId());
        return true;
    }

    /**
     * 1.role是否存在，存在返回false
     * 2.先更新role基础信息
     * 3.再判断是否需要更新资源关联关系（是：删除原有关联关系，再绑定新的关联关系；否：true）
     * @param rolePo
     * @return
     */
    @Override
    @Transactional(rollbackFor=Exception.class)
    public boolean update(RolePo rolePo) {
        Role role= baseMapper.selectOne(new LambdaQueryWrapper<Role>().eq(Role::getId,rolePo.getId()));
        Assert.isNull(role, RoleEnum.ROLE_NOT_EXIST.getMsg());
        baseMapper.updateById(rolePo);
        if(isUpdate(rolePo.getResourceIds(),rolePo.getId())){
            roleResourceDao.delete(new LambdaQueryWrapper<RoleResource>().eq(RoleResource::getRoleId,rolePo.getId()));
            saveRoleResource(rolePo.getResourceIds(),rolePo.getId());
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor=Exception.class)
    public boolean deleteRolesAndLinked(List<Serializable> ids) {
        for (Serializable id:ids){
            Role role = baseMapper.getRoleByIsDefault(id);
            Assert.isTrue(role!=null,RoleEnum.NOT_ALLOWED_DEl_DEFAULT_ROLE.getMsg());
            roleIsUse(id);
            roleResourceDao.delete(new LambdaQueryWrapper<RoleResource>().eq(RoleResource::getRoleId,id));
        }
        deleteBatch(ids);
        return true;
    }

    @Override
    public Set<String> queryUserRoles(User user) {
        List<Role> list = baseMapper.queryUserRoles(user);
        Set<String> roles = new HashSet<>();
        for (Role role:list){
            roles.add(role.getRoleKey());
        }
        return roles;
    }

    @Override
    public List<Role> findByUserId(User user) {
        return baseMapper.queryUserRoles(user);
    }

    /**
     * 保存角色菜单关系
     * @param resourceIds
     * @param roleId
     */
    @Transactional(rollbackFor=Exception.class)
    protected void saveRoleResource(String resourceIds,String roleId){
        if(!StringUtils.isEmpty(resourceIds)){
            String[] resources = resourceIds.split(SysConstant.SPLIT_REGEX);
            for(String id:resources){
                RoleResource roleResource = new RoleResource();
                roleResource.setRoleId(roleId);
                roleResource.setResourceId(id);
                roleResourceDao.insert(roleResource);
            }
        }
    }

    /**
     * 是否需要更新role-resource的关联关系
     * 1.都不为空情况下：
     * @param resourceIds
     * @param roleId
     * @return boolean
     */
    protected boolean isUpdate(String resourceIds,String roleId){
        List<RoleResource> roleResources = roleResourceDao.selectList(new LambdaQueryWrapper<RoleResource>().eq(RoleResource::getRoleId,roleId));
        if(!StringUtils.isEmpty(resourceIds)&&!roleResources.isEmpty()){
            String[] resources = resourceIds.split(SysConstant.SPLIT_REGEX);
            for (String id:resources){
                boolean flag = false;
                for (RoleResource roleResource:roleResources){
                    if(id.equals(roleResource.getResourceId())){
                        flag = true;
                    }
                }
                if(!flag){
                    return true;
                }
            }
        }
        if(StringUtils.isEmpty(resourceIds) && roleResources.isEmpty()){
            return false;
        }
        return true;
    }

    protected void roleIsUse(Serializable id){
        List<User> names = baseMapper.getRoleUser(id);
        StringBuffer sb = new StringBuffer();
        for (User user:names){
            sb.append(user.getUsername()+"、");
        }
        if(sb.length()>1){
            sb.deleteCharAt(sb.length() - 1);
        }
        Assert.isTrue(!names.isEmpty(),sb.toString()+RoleEnum.ROLE_IS_USE.getMsg());
    }
}